package com.nulldev.util.networking.async2.udp;

import java.net.DatagramPacket;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.networking.async2.events.ManualResetEvent;

public final class IncomingUDPServerPacket implements Runnable {
	private ManualResetEvent fDone = new ManualResetEvent(false);
	private boolean fCancel = false;
	private UDPListener fListener;
	private DatagramPacket fData;
	private IncomingUDPServerPacket fPreviousPacket;

	/**
	 * Constructs a new incoming UDP packet.
	 * 
	 * Use this class to receive data from a client. This is an incoming message
	 * that will remain in the servers thread pool as a job for the thread pool
	 * workers.
	 * 
	 * @param listener       is the listener caught the message.
	 * @param packet         is a Datagram packet.
	 * @param previousPacket is the previous incoming message of the listener.
	 */
	public IncomingUDPServerPacket(final UDPListener listener, final DatagramPacket packet, final IncomingUDPServerPacket previousPacket) {
		this.fListener = listener;
		this.fData = packet;
		listener.getUDPServer().fThreadPool.execute(this);
	}

	/**
	 * Cancel this incoming packet.
	 * 
	 * By calling this method this and all the previous incoming packets that are
	 * stored in the thread pool will be canceled. Call this method for the last
	 * incoming packet of the server when the server stops.
	 * 
	 */
	public void cancel() {
		this.fCancel = true;
		this.fDone.set();
	}

	@Override
	public void run() {
		try {
			if (this.fPreviousPacket == null) {
				this.fListener.getUDPServer().onDataReceive(this.fListener, fData);
			} else {
				this.fPreviousPacket.fDone.waitOne();
				if (!this.fCancel && !this.fPreviousPacket.fCancel) {
					this.fListener.getUDPServer().onDataReceive(this.fListener, fData);
				} else {
					JVM.println("IncomingUDPServerPacket canceled!");
					this.fCancel = true;
				}

			}
		} catch (Exception ex) {
		}

		if (this.fPreviousPacket != null) {
			this.fPreviousPacket = null;
		}

		this.fDone.set();
	}

	/**
	 * Returns the DatagramPacket of this incoming UDP packet.
	 * 
	 * @return the DatagramPacket of this incoming UDP packet.
	 */
	public DatagramPacket getData() {
		return this.fData;
	}

	/**
	 * Returns the previus incoming packet received by the server. If the packet is
	 * null means that the packet has been received and parsed from the server.
	 * 
	 * @return the previus incoming packet received by the server.
	 */
	public IncomingUDPServerPacket getPreviusPacket() {
		return this.fPreviousPacket;
	}
}
